package cn.tedu.fruitshop.config;

import cn.tedu.fruitshop.filter.JwtAuthorizationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Spring Security框架的配置类
 *
 * @author www
 * @create 2022-11-07 10:35
 */
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthorizationFilter jwtAuthorizationFilter;

    public SecurityConfiguration() {
        log.debug("启动配置类：SecurityConfiguration");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
//        return NoOpPasswordEncoder.getInstance();
        log.debug("密码编码方法被调用：passwordEncoder，创建一个新的BCrypt密码编码");
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        /**
         * 静态资源直接过滤
         */
        String[] urls = {
                "/**/*.min.css",
                "/css/**",
                "/js/**",
                "/img/**",
                "/fonts/**",
                "/verifyCode",
                "/swagger-resources",
                "/**/*.ioc",
                "/**/*.js",
                "/**/*.jpg",
                "/**/*.webp",
                "/**/*.png",
                "/**/*.css",
                "/**/*.woff2",
                "/v2/api-docs",
                "/**/*.html",
                "/detail.html",
                "/address.html",
                "/addressadd.html",
                "/updateaddress.html"
        };
        web.ignoring().antMatchers(urls);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        log.debug("开始执行：authenticationManagerBean");
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //如果不调用父类方法，默认所有请求都不需要通过认证，可以直接访问
        // super.configure(http);
//        http.authorizeRequests()                //管理请求授权
//                .mvcMatchers("/**")     //匹配某些路径
//                .authenticated();               //要求是"已经通过认证的"
        //白名单
        String[] urls = {
                "/user/**",
                "/menus",
                "/itemCategory",
                "/itemCategory/selectByParentId",
                "/user/admin/selectByUsername",
                "/address",
                "/address/add-new",
                "/address/{location}/delete",
                "/address/update",
                "/user/admin/selectByUsername",
                "/orders",
                "/role",
                "/itemCategory/**",
                "/item/add-new",
                "/upload",
                "/item",
                "/item/list",
                "/item/**"
        };

        //解决跨源访问
        http.cors();

        //将防止 伪造跨域攻击 的机制禁用
        http.csrf().disable();
        //创建授权请求
        log.debug("开始创建授权请求");
        http.authorizeRequests()
                //配置需要设置的路径
                .mvcMatchers(urls)
                //以上路径都可以直接访问不需要认证
                .permitAll()
                //除了以上配置的路径外，所有请求
                .anyRequest()
                //需要通过验证。
                .authenticated();
        log.debug("路径通过");
        //在Security框架的身份验证过滤器之前添加 jwt授权的过滤器
        http.addFilterAfter(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);

        //启用登录表单
        //当未认证时：
        //  -- 启用登录表单,重定向到登录页面；
        //  -- 不启用，会提示403错误
        http.formLogin();

    }
}
